<!DOCTYPE html>
<html lang="en">
    <head>
    <title>Rust - Exploring Lifetime Problems - 3 - Tinusgraglin</title>
    
    
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1"><meta name="description" content="A Slice Rust - Exploring Lifetime Problems - 3 How should we understand this?"/><meta name="keywords" content="rust, rust-language, rust-lifetime" />
    <meta property="og:title" content="A Slice of Tgl -&nbsp;Rust - Exploring Lifetime Problems - 3" />
    <meta property="og:type" content="website"/><meta property="og:url" content="&#x2F;blog&#x2F;rust-explore-lifetime-problems-3&#x2F;"/><meta property="og:description" content="How should we understand this?"/>
    <link rel="preload" href="/blog/assets/fonts/FiraCode-Regular.woff2" as="font" type="font/woff2" crossorigin="anonymous">
    <link rel="preload" href="/blog/assets/fonts/FiraCode-Bold.woff2" as="font" type="font/woff2" crossorigin="anonymous">

    <link rel="stylesheet" href="/blog/style.css?h=97e262212a0704163528">
    <link rel="stylesheet" href=" /blog/color/orange.css?h=a5a5d7faf9d4bc3e0b18">
    
</head>
    <body>
        <div class="container center">
<header class="header">
    <div class="header__inner">
        <div class="header__logo">
            <a href="&#x2F;blog">
    <div class="logo">
        LIN
    </div>
</a>
        </div>
        <div class="menu-trigger">menu</div>
    </div>
    
    <nav class="menu">
        <ul class="menu__inner menu__inner--desktop">
            
            
                    <li>
                        <a href="
    
        /blog/about
    
">about</a>
                    </li>
                
            </ul>

        <ul class="menu__inner menu__inner--mobile">
            
        <li>
            <a href="
    
        /blog/about
    
">about</a>
        </li>
        </ul>
    </nav>

    </header>
<div class="content"><article class="post">
        <header>
            <h1 class="post-title">
                <a href="&#x2F;blog&#x2F;rust-explore-lifetime-problems-3&#x2F;">Rust - Exploring Lifetime Problems - 3</a>
            </h1>
            
    <div class="post-meta">
        <span class="post-date">2023.12.27
                [Updated: 2023.12.27]
                </span>

        <span class="post-author"></span>

        

    
    :: {<a href="/blog/categories/rust/">rust</a>} 

            
    ::
    #<a href="/blog/tags/rust-language/">rust-language</a>
        
    #<a href="/blog/tags/rust-lifetime/">rust-lifetime</a>
        
    
            
        
    </div>

            
    
</header><p>I hit this lifetime problem when trying to change a mutable reference itself:</p>
<pre data-lang="rust" style="background-color:#2b303b;color:#c0c5ce;" class="language-rust "><code class="language-rust" data-lang="rust"><span style="color:#b48ead;">struct </span><span>St&lt;</span><span style="color:#b48ead;">&#39;a</span><span>&gt;(&amp;</span><span style="color:#b48ead;">&#39;a mut</span><span> [</span><span style="color:#b48ead;">usize</span><span>])
</span><span>
</span><span style="color:#b48ead;">impl</span><span>&lt;</span><span style="color:#b48ead;">&#39;a</span><span>&gt; St&lt;</span><span style="color:#b48ead;">&#39;a</span><span>&gt; {
</span><span>    </span><span style="color:#b48ead;">fn </span><span style="color:#8fa1b3;">change</span><span>&lt;</span><span style="color:#b48ead;">&#39;some_lifetime</span><span>&gt;(&amp;</span><span style="color:#b48ead;">&#39;some_lifetime mut </span><span style="color:#bf616a;">self</span><span>) {
</span><span>        </span><span style="color:#65737e;">// The compiler complains that &#39;some_lifetime should be
</span><span>        </span><span style="color:#65737e;">// as long as &#39;a:
</span><span>        </span><span style="color:#bf616a;">self</span><span>.</span><span style="color:#d08770;">0 </span><span>= &amp;</span><span style="color:#b48ead;">mut </span><span style="color:#bf616a;">self</span><span>.</span><span style="color:#d08770;">0</span><span>[</span><span style="color:#d08770;">1</span><span>..];
</span><span>    }
</span><span>}
</span></code></pre>
<p>But changing a shared reference is fine:</p>
<pre data-lang="rust" style="background-color:#2b303b;color:#c0c5ce;" class="language-rust "><code class="language-rust" data-lang="rust"><span style="color:#b48ead;">struct </span><span>St&lt;</span><span style="color:#b48ead;">&#39;a</span><span>&gt;(&amp;</span><span style="color:#b48ead;">&#39;a</span><span> [</span><span style="color:#b48ead;">usize</span><span>])
</span><span>
</span><span style="color:#b48ead;">impl</span><span>&lt;</span><span style="color:#b48ead;">&#39;a</span><span>&gt; St&lt;</span><span style="color:#b48ead;">&#39;a</span><span>&gt; {
</span><span>    </span><span style="color:#b48ead;">fn </span><span style="color:#8fa1b3;">change</span><span>&lt;</span><span style="color:#b48ead;">&#39;some_lifetime</span><span>&gt;(&amp;</span><span style="color:#b48ead;">&#39;some_lifetime mut </span><span style="color:#bf616a;">self</span><span>) {
</span><span>        </span><span style="color:#65737e;">// Works:
</span><span>        </span><span style="color:#bf616a;">self</span><span>.</span><span style="color:#d08770;">0 </span><span>= &amp;</span><span style="color:#bf616a;">self</span><span>.</span><span style="color:#d08770;">0</span><span>[</span><span style="color:#d08770;">1</span><span>..];
</span><span>    }
</span><span>}
</span></code></pre>
<p>Let's see the first case <code>self.0 = &amp;mut self.0[1..]</code>, the left side expects a <code>&amp;'a mut [usize]</code>,
the right side is actually <code>std::ops::IndexMut::index_mut(self.0, 1..)</code>, note that since <code>self.0</code>
is of type <code>&amp;mut T</code> which <em>is not</em> <code>Copy</code>, there is an implicit reborrow: <code>index_mut(&amp;mut *self.0, 1..)</code>,
which basically creates another temporary <code>&amp;'temp mut [usize]</code>, since it is created to be used inside
the function, we have <code>'some_lifetime: 'temp</code>, but <code>'temp</code> has to be <code>'a</code> to satisfy the left side, so
we now must have <code>'some_lifetime: 'a</code>.</p>
<p>In the second case, the line expands to <code>self.0 = std::ops::Index::index(self.0, 1..)</code> <code>self.0</code> is of type
<code>&amp;T</code> which <em>is</em> <code>Copy</code>, so the complication above does not come up.</p>
<p>One way to solve the problem in the first case without requiring <code>'some_lifetime: 'a</code> is to move the exclusive
reference out using <code>std::mem::{take,replace,swap}</code>:</p>
<pre data-lang="rust" style="background-color:#2b303b;color:#c0c5ce;" class="language-rust "><code class="language-rust" data-lang="rust"><span style="color:#b48ead;">struct </span><span>St&lt;</span><span style="color:#b48ead;">&#39;a</span><span>&gt;(&amp;</span><span style="color:#b48ead;">&#39;a mut</span><span> [</span><span style="color:#b48ead;">usize</span><span>])
</span><span>
</span><span style="color:#b48ead;">impl</span><span>&lt;</span><span style="color:#b48ead;">&#39;a</span><span>&gt; St&lt;</span><span style="color:#b48ead;">&#39;a</span><span>&gt; {
</span><span>    </span><span style="color:#b48ead;">fn </span><span style="color:#8fa1b3;">change</span><span>&lt;</span><span style="color:#b48ead;">&#39;some_lifetime</span><span>&gt;(&amp;</span><span style="color:#b48ead;">&#39;some_lifetime mut </span><span style="color:#bf616a;">self</span><span>) {
</span><span>        </span><span style="color:#65737e;">// since `&amp;mut [T]` implements `Default` (with default value `&amp;mut []`),
</span><span>        </span><span style="color:#65737e;">// we can use `std::mem::take`:
</span><span>        </span><span style="color:#b48ead;">let</span><span> r_mut = std::mem::take(&amp;</span><span style="color:#b48ead;">mut </span><span style="color:#bf616a;">self</span><span>.</span><span style="color:#d08770;">0</span><span>);
</span><span>        </span><span style="color:#bf616a;">self</span><span>.</span><span style="color:#d08770;">0 </span><span>= std::ops::IndexMut::index_mut(r_mut, </span><span style="color:#d08770;">1</span><span>..);
</span><span>    }
</span><span>}
</span></code></pre>


        
    

        
        
    </article></div>
    <div class="pagination">
        <div class="pagination__buttons">
            </div>
    </div>
<footer class="footer">
                    <div class="footer__inner"><div class="copyright">
            <span>© 2024 Tinusgraglin <span/>
            <span>:: Powered by <a href="https://www.getzola.org/">Zola</a>(<a href="https://www.rust-lang.org/">Rust</a>) and <a href="https://bun.sh">Bun</a>(<a href="https://ziglang.org">Zig</a>)</span>
        </div>
    <script type="text/javascript" src="/blog/assets/js/main.js"></script>
</div>
                    

                </footer></div>
    </body>
</html>
